<template>
  <div class="flex-column bg-gray pd0 gap16">
    <div class="top pd10 flex-column bg-white">
      <div class="bold" style="margin-bottom: 12px">代理概览</div>
      <div class="flex-row-center-between flex1 gap20">
        <TopOverviewMonth :data="state.rawGraphData.partsVO" />
        <TopOverviewAll :data="state.rawGraphData.partsVO" />
      </div>
    </div>

    <div class="flex-column flex1 gap16">
      <div class="flex1 bg-white flex-column pd10">
        <div v-show="state.rawGraphData?.faultPartsTopList?.length" class="bold">故障部件排序</div>
        <div v-show="state.rawGraphData?.faultPartsTopList?.length" id="graph-part" class="flex1 width-all"></div>
        <empty v-if="!state.rawGraphData?.faultPartsTopList?.length" style="margin: auto" />
      </div>

      <div class="flex1 bg-white flex-column pd10">
        <div v-show="!isEmpty(state.rawGraphData.changeTrendMap)" class="flex1 flex-column">
          <div class="flex-row-center-left">
            <div class="bold">故障部件变化趋势</div>
            <div class="mgl30 flex-row-center-left">
              <SelectVue style="width: 150px" v-model="state.monthQuery.startTime" :option-list="monthRange" @change="onMonthChange" :clearable="false" />
              <span class="grey-text mgl5 mgr5">至</span>
              <SelectVue style="width: 150px" v-model="state.monthQuery.endTime" :option-list="monthRange" @change="onMonthChange" :clearable="false" />
            </div>
          </div>
          <div id="graph-trend" class="flex1 width-all"></div>
        </div>
        <empty v-show="isEmpty(state.rawGraphData.changeTrendMap)" style="margin: auto" />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { reactive, onMounted, onUnmounted, nextTick } from 'vue'
  import TopOverviewMonth from './cpns/top-overview-month.vue'
  import TopOverviewAll from './cpns/top-overview-all.vue'
  import SelectVue from '@/components/select'
  import * as echarts from 'echarts'
  import type { ECharts } from 'echarts'
  import { max, min, isEmpty, uniq } from 'xe-utils'
  import request from '@/service'
  import { Ui } from '@/utils'
  import type {} from './config'
  import { setChartOptions, setChartOptionsByTrend } from './config'
  import type { GraphData, FaultPartsTopItem, ChangeTrendItem, SetOptionData } from './config'
  import empty from '@/components/empty/empty.vue'

  type PartTrendData = [string, ChangeTrendItem[]]

  interface PartDataMap {
    [key: string]: number[]
  }

  const initData = (): SetOptionData => ({
    xAxisData: [],
    faultData: [],
    rateData: [],
    yAxisLeftMax: 0,
    yAxisRightMax: 0,
    yAxisRightMin: 0
  })

  const state = reactive({
    rawGraphData: {} as GraphData,
    monthGraphData: initData(),
    monthQuery: {
      startTime: '',
      endTime: ''
    }
  })

  let monthChart: ECharts
  let trendChart: ECharts
  let monthRange: string[] = []
  let partTrendList: PartTrendData[] = []

  /**----------------------------methods----------------------------------------------------------------------- */

  const resize = () => {
    monthChart.resize()
    trendChart.resize()
  }

  const initGraph = () => {
    monthChart = echarts.init(document.getElementById('graph-part'))
    trendChart = echarts.init(document.getElementById('graph-trend'))

    window.addEventListener('resize', resize)
  }

  const mapGraphData = (list: FaultPartsTopItem[]) => {
    state.monthGraphData.xAxisData = list.map(item => item.dateString)

    state.monthGraphData.faultData = list.map(item => item.dateCount)
    state.monthGraphData.rateData = list.map(item => parseFloat(item.dateRate.replace('%', '')))

    const maxFaultItem = max(list, 'dateCount') as FaultPartsTopItem

    const maxRateItem = max(list, item => parseFloat(item.dateRate.replace('%', ''))) as FaultPartsTopItem
    const minRateItem = min(list, item => parseFloat(item.dateRate.replace('%', ''))) as FaultPartsTopItem

    state.monthGraphData.yAxisLeftMax = maxFaultItem.dateCount
    state.monthGraphData.yAxisRightMax = parseFloat(maxRateItem.dateRate.replace('%', ''))
    state.monthGraphData.yAxisRightMin = parseFloat(minRateItem.dateRate.replace('%', ''))
    if (state.monthGraphData.yAxisRightMin > 0) state.monthGraphData.yAxisRightMin = 0

    setChartOptions(monthChart, state.monthGraphData)
  }

  /**选择时间 */
  const onMonthChange = () => {
    const r = (str: string) => str.replace('.', '')
    const { startTime, endTime } = state.monthQuery

    const rStart = r(startTime)
    const rEnd = r(endTime)

    if (rStart > rEnd) return Ui.useMessage('warning', '月份间隔无效，请重新选择')

    const list = partTrendList.filter(item => r(item[0]) >= rStart && r(item[0]) <= rEnd)

    mapTrendData(list)
  }

  /**部件趋势图 */
  const mapTrendData = (trendList: PartTrendData[]) => {
    // x轴
    const xAxisData = trendList.map(item => item[0])
    //  部件最多的月份
    let mostPartMonth: ChangeTrendItem[] = []

    trendList.forEach(item => {
      if (item[1].length > 1) mostPartMonth = mostPartMonth.concat(item[1])
      item[1][0].part && mostPartMonth.push(item[1][0])
    })

    mostPartMonth = uniq(mostPartMonth, 'part')

    //转换为 key为部件value为部件对应的数据数组 PartDataMap
    const partDataMap = mostPartMonth.reduce<PartDataMap>((mapDta, partData) => {
      mapDta[partData.part] = trendList.map(item => {
        const findItem = item[1].find(info => info.part === partData.part) ?? { percentage: '0%' }
        return Number(findItem.percentage.replace('%', ''))
      })

      return mapDta
    }, {})

    // 转换
    const series = Object.entries(partDataMap).map(item => {
      return {
        name: item[0],
        data: item[1],
        type: 'line'
      }
    })

    setChartOptionsByTrend({
      chart: trendChart,
      xAxisData,
      yMax: 100,
      yMin: 0,
      series,
      legendData: Object.keys(partDataMap)
    })
  }

  /**获取数据 */
  const getGraphData = () => {
    request.get<GraphData>('/fault/getFaultParts').then(res => {
      if (res.code !== 0) return Ui.useMessage('error', res.msg)

      const { faultPartsTopList, changeTrendMap } = res.data

      partTrendList = Object.entries(changeTrendMap)

      state.rawGraphData = res.data

      monthRange = partTrendList.map(item => item[0])

      state.monthQuery.startTime = monthRange[0]
      state.monthQuery.endTime = monthRange.at(-1) as string

      nextTick(() => {
        initGraph()

        // 故障 部件 排序
        if (faultPartsTopList.length) mapGraphData(faultPartsTopList)

        // 趋势
        if (!isEmpty(changeTrendMap)) mapTrendData(partTrendList)
      })
    })
  }

  /**----------------------------lifecycle----------------------------------------------------------------------- */

  onMounted(() => {
    getGraphData()
  })

  onUnmounted(() => {
    monthChart.dispose()
    trendChart.dispose()
    window.removeEventListener('resize', resize)
  })
</script>

<style scoped lang="less">
  // .top {
  //   height: 150px;
  //   flex-shrink: 0;
  // }
</style>
